package com.gregbugaj.gps;

/**
 * http://www.meridianworlddata.com/Distance-Calculation.asp:
 * 
 * @author devil
 * 
 */
public class DistanceSpeedUtil {
	// Radius of earth
	private static final int EARTH_RADIUS = 3963;
	private static final int FEET_PER_MILE = 5280;
	private static final int METERS_PER_KILOMETER = 1000;
	private static final int SECONDS_PER_HOUR = 3600;

	// 1 foot / second = 0.681818182 miles / hour
	private static final double MILES_PER_HOUR=0.681818182;


	//1 KM = 0.621371192 Mile
	private static final double KM_IN_MILE=0.621371192;



	public static void main(String[] args) {
		System.out.println("Running");
		/*
		 * 440 / 8 =55 mil/h
		 */
		double fps=getSpeed(440*FEET_PER_MILE, 7*SECONDS_PER_HOUR);
		System.out.println("fps="+fps);
		System.out.println("mph="+convertFPStoMPH(fps));

		System.out.println("-----------------");
		double lat1=(35.4500);
		double lon1=(-97.4600);

		double lat2=(35.4500);
		double lon2=(-97.46003);

		double distanceInKM=getDistanceInKM(lat1, lon1, lat2, lon2);
		System.out.println("distance in KM    = "+distanceInKM);
		System.out.println("distance in MIles = "+convertKMtoM(distanceInKM));	
		System.out.println("Miles To Feet = "+convertMilesToFeet(convertKMtoM(distanceInKM)));
		System.out.println("Kilometers To Meters = "+convertKilometersToMeter(distanceInKM));
	}

	/**
	 * Convert distance in miles to feet round up
	 * @param distance
	 * @return
	 */
	public static long convertMilesToFeet(double distance){
		return Math.round(distance*FEET_PER_MILE);
	}

	/**
	 * Convert distance in Kilometers to meters round up
	 * @param distance
	 * @return
	 */
	public static long convertKilometersToMeter(double distance){
		return Math.round(distance*METERS_PER_KILOMETER);
	}

	/**
	 * Get the speed we are traveling at
	 * speed=D/T
	 * 
	 * @param distance in feet            
	 * @param speed in seconds
	 * @return speed in feet/second
	 */
	public static double getSpeed(double distance, double time) {
		double speed = distance / time;
		return speed;
	}

	public static double convertFPStoMPH(double distanceInFPS){
		return distanceInFPS*MILES_PER_HOUR;
	}

	public static double convertKMtoM(double kilometers){
		return kilometers * KM_IN_MILE;
	}

	/**
	 * Calculate distance between two points
	 * 
	 * @param fromPoint
	 * @param toPoint
	 * @return
	 */
	/*
	 * public double getDistance(GeoPoint fromPoint, GeoPoint toPoint){
	 * 
	 * long lat1=fromPoint.getLatitudeE6(); long lat2=toPoint.getLatitudeE6();
	 * 
	 * long lon1=fromPoint.getLongitudeE6(); long lon2=toPoint.getLongitudeE6();
	 * 
	 * return getDistance(lat1, lon1, lat2, lon2); }
	 */
	/**
	 * Get distance
	 * 
	 * @param lat1
	 * @param lon1
	 * @param lat2
	 * @param lon2
	 * @return distance in feet
	 */
	public static double getDistanceInKM(double lat1, double lon1, double lat2, double lon2) {
		/*
		double GCDistance = EARTH_RADIUS
		 * Math.acos(Math.sin(lat1 / 57.2958) * Math.sin(lat2 / 57.2958)
						+ Math.cos(lat1 / 57.2958) * Math.cos(lat2 / 57.2958)
		 * Math.cos(lon2 / 57.2958 - lon1 / 57.2958));
		 */

		//http://www.movable-type.co.uk/scripts/latlong.html
		//Works good with small distances also 
		int R = 6371; // km
		double dLat = Math.toRadians((lat2-lat1));
		double dLon = Math.toRadians((lon2-lon1)); 
		double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
		Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * 
		Math.sin(dLon/2) * Math.sin(dLon/2); 
		double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
		double d = R * c;
		return d;
	}

	/**
	 * Get distance
	 * @param lat1
	 * @param lon1
	 * @param lat2
	 * @param lon2
	 * @return
	 */
	public static double getDistanceInKM(Latitude lat1, Longitude lon1, Latitude lat2, Longitude lon2){
		return getDistanceInKM(lat1.getDecimal(), lon1.getDecimal(), lat2.getDecimal(), lon2.getDecimal());
	}
}
